package com.zz.springboot.service.impl;

import com.zz.springboot.constant.TypeConstants;
import com.zz.springboot.dto.DataDTO;
import com.zz.springboot.dto.MaxMoneyParamDto;
import com.zz.springboot.exception.BizException;
import com.zz.springboot.holder.ParamDataHolder;
import com.zz.springboot.manager.AoMenManager;
import com.zz.springboot.manager.BaseManager;
import com.zz.springboot.manager.MaxMoneyParamManager;
import com.zz.springboot.manager.XiangGangManager;
import com.zz.springboot.model.ExcludeInfo;
import com.zz.springboot.processor.DataProcessorFactory;
import com.zz.springboot.resp.enums.RespCodeEnum;
import com.zz.springboot.service.GenerateService;
import com.zz.springboot.util.DataDealUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GenerateServiceImpl implements GenerateService {

    @Autowired
    AoMenManager aoMenManager;

    @Autowired
    XiangGangManager xiangGangManager;

    @Autowired
    MaxMoneyParamManager maxMoneyParamManager;

    @Autowired
    private DataProcessorFactory dataProcessorFactory;


    Lock lock = new ReentrantLock();

    @Override
    //@Async("threadPoolTaskExecutor")
    public void parseData(String originData, Integer type) {
        /** ------------ 1.解析原始字符串数据，封装为List ------------**/
        // List<String> dataList = DataDealUtils2.parseData(originData);
        //1.1 处理中文字符
        String data = DataDealUtils.chineseCharacterProceess(originData);
        //1.2 分类处理数据，以List<String>进行封装
        List<String> dataList = dataProcessorFactory.getProcessor(data).process(data);
        log.info("{}，原始数据封装的List：{}", type == 1 ? "澳门" : "香港", dataList);

        /** ------------ 2.数据实体类包装 ------------**/
        // 封装进实体类
        List<DataDTO> dataDtos = DataDealUtils.listToModel(dataList);
        log.info("{}，实体类数据为：{}", type == 1 ? "澳门" : "香港", dataDtos);

        // 初始化数据
        if (TypeConstants.AOMEN.equals(type)) {
            initialData(dataDtos, aoMenManager, TypeConstants.AOMEN);
        } else {
            initialData(dataDtos, xiangGangManager, TypeConstants.XiangGang);
        }

    }


    public void initialData(List<DataDTO> dataList, BaseManager baseManager, Integer type) {
        //lock.lock();
        List<Integer> numSet;             //表中所有号码
        List<DataDTO> insertList;   // 新增数据集合
        List<DataDTO> updateList;   // 更新数据集合

//        try {
        //获得表中所有数据
        List<DataDTO> allData = baseManager.selectAllData();
        numSet = allData.stream().map(u -> u.getNum()).collect(Collectors.toList());
        //Collectors.toMap()中要注意key不能重复！
        Map<Integer, DataDTO> dataMap = allData.stream().collect(Collectors.toMap(u -> u.getNum(), u -> u));

        insertList = getInsertData(dataList, numSet);
        updateList = getUpdateData(dataList, numSet);

        if (!CollectionUtils.isEmpty(insertList)) {  //处理表中不存在号码的数据：新增
            for (DataDTO dataDTO : insertList) {
                calculateInitialValue(dataDTO, type);
            }
            baseManager.insertBatchData(insertList);
        }
        if (!CollectionUtils.isEmpty(updateList)) {  //处理表中存在号码的数据：更新
            for (DataDTO dataDto : updateList) {
                DataDTO tableData = dataMap.get(dataDto.getNum());
                float existBuyMoney = tableData.getBuyMoney();
                dataDto.setBuyMoney(existBuyMoney + dataDto.getBuyMoney());
                calculateInitialValue(dataDto, type);
            }
            baseManager.updateBatchData(updateList);
        }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            lock.unlock();
//        }


    }

    @Override
    public String printAllExcludeInfo(Integer type) {
        List<ExcludeInfo> allExcludeInfo = new ArrayList<>();
        if (TypeConstants.AOMEN.equals(type)) {
            allExcludeInfo = aoMenManager.getAllExcludeInfo();
        } else if (TypeConstants.XiangGang.equals(type)) {
            allExcludeInfo = xiangGangManager.getAllExcludeInfo();
        } else {
            throw new BizException(RespCodeEnum.PARAMS_VERIFY_FAIL);
        }

        StringBuilder sb = new StringBuilder(type == 1 ? "【澳门】" : "【香港】");
        String result;
        for (ExcludeInfo info : allExcludeInfo) {
            result = info.getNum() + "/" + info.getExcludeMoney();
            sb.append(result + " ");
        }

        return sb.toString();
    }

    /**
     * 初始化【报出金额】和【消化金额】
     *
     * @param dataDTO
     */
    public void calculateInitialValue(DataDTO dataDTO, Integer type) {
        Integer AOMEN_MAX_VALUE = 0;  //澳门码单个号子最大的恰码数
        Integer XiangGang_MAX_VALUE = 0;  //香港码单个号子最大的恰码数

        Session session = SecurityUtils.getSubject().getSession();
        String username = (String) session.getAttribute("username");
        // 1.若无缓存
        if (ParamDataHolder.getMaxMoneyParam(username) == null) {
            MaxMoneyParamDto maxMoneyParamDto = maxMoneyParamManager.getMaxMoneyParam(username);
            // 1.1 无缓存，数据库有设置
            if (maxMoneyParamDto == null) {
                log.info("******用户{}没有设置【最大金额】参数！将使用默认金额", username);
                ParamDataHolder.setMaxMoneyParamMap(username, new MaxMoneyParamDto(AOMEN_MAX_VALUE, XiangGang_MAX_VALUE));
            } else { // 1.2 无缓存，但数据库中有设置
                ParamDataHolder.setMaxMoneyParamMap(username, maxMoneyParamDto);
            }
        }
        // 2.若有缓存
        AOMEN_MAX_VALUE = ParamDataHolder.getMaxMoneyParam(username).getAomenMaxValue();
        XiangGang_MAX_VALUE = ParamDataHolder.getMaxMoneyParam(username).getXianggangMaxValue();

        if (TypeConstants.AOMEN.equals(type)) {
            DataDealUtils.calculateInitialValue(dataDTO, AOMEN_MAX_VALUE);
        } else {
            DataDealUtils.calculateInitialValue(dataDTO, XiangGang_MAX_VALUE);
        }
    }


    /**
     * 获得存在集合originDataDTOList中、但不存在集合numSet中的号码
     *
     * @param dataDTOList
     * @param numSet
     * @return
     */
    public List<DataDTO> getInsertData(List<DataDTO> dataDTOList, List<Integer> numSet) {

        return dataDTOList.stream().filter(u -> !numSet.contains(u.getNum())).collect(Collectors.toList());
    }

    /**
     * 获得存在集合originDataDTOList中、且存在集合numSet中的号码（待更新）
     *
     * @return
     */
    public List<DataDTO> getUpdateData(List<DataDTO> dataDTOList, List<Integer> numSet) {
        return dataDTOList.stream().filter(u -> numSet.contains(u.getNum())).collect(Collectors.toList());
    }


    @Override
    public void clearAoMenTable() {
        aoMenManager.clearTable();
    }

    @Override
    public void clearXiangGangTable() {
        xiangGangManager.clearTable();
    }
}
